using Cysharp.Threading.Tasks;
using System;
using UnityEngine;
using YooAsset;

namespace LFramework
{
    /// <summary>
    /// 场景管理器
    /// </summary>
    public class LSceneManager : IDisposable
    {
        /// <summary>
        /// 加载完毕委托
        /// </summary>
        private Action m_OnComplete = null;

        /// <summary>
        /// 场景是否加载中
        /// </summary>
        private bool m_CurrSceneIsLoading;

        /// <summary>
        /// 当前进度
        /// </summary>
        private float m_CurrProgress = 0;

        /// <summary>
        /// 目标进度
        /// </summary>
        private float m_TargetProgress = 0;

        /// <summary>
        /// 加载场景进度监听事件
        /// </summary>
        public event Action<float> LoadingUpdateAction;

        /// <summary>
        /// 当前场景名称
        /// </summary>
        private string m_CurrScreenName = string.Empty;

        /// <summary>
        /// 加载场景的句柄
        /// </summary>
        private SceneHandle m_SceneHandle = null;

        /// <summary>
        /// 用来传递加载进度的 float类
        /// </summary>
        private VarFloat m_EventProgressValue = null;

        public LSceneManager()
        {
            m_EventProgressValue = new VarFloat();
        }

        /// <summary>
        /// 加载场景
        /// </summary>
        public UniTask LoadSceneAsync(string sceneName, int sceneLoadCount = -1)
        {
            var task = new UniTaskCompletionSource();
            LoadSceneAction(sceneName , () =>
            {
                task.TrySetResult();
            }, sceneLoadCount);
            return task.Task;
        }

        public void LoadSceneAction(string sceneName , Action onComplete = null, int sceneLoadCount = -1)
        {
            if (m_CurrSceneIsLoading)
            {
                GameEntry.LogError(string.Format("场景{0}正在加载中", m_CurrScreenName));
                return;
            }
            m_CurrSceneIsLoading = true;

            m_OnComplete = onComplete;
            if (m_CurrScreenName == sceneName)
            {
                GameEntry.LogError(string.Format("正在重复加载场景{0}", sceneName));
                m_OnComplete?.Invoke();
                return;
            }

            m_CurrProgress = 0;
            m_CurrScreenName = sceneName;

            //卸载当前场景并加载新场景
            if (m_SceneHandle != null)
            {
                UnLoadScene();
            }
            else
            {
                LoadNewScene();
            }
        }

        private void LoadNewScene()
        {
            m_SceneHandle = YooAssets.LoadSceneAsync(m_CurrScreenName);
        }

        private void UnLoadScene() 
        {
            if (m_SceneHandle != null)
            {
                m_SceneHandle.UnloadAsync().Completed += SceneUnloadCB;
            }
            else 
            {
                GameEntry.Log("卸载的场景不存在");
            }
        }

        private void SceneUnloadCB(AsyncOperationBase op)
        {
            m_SceneHandle = null;
            Resources.UnloadUnusedAssets();
            GC.Collect();
            LoadNewScene();
        }

        public void OnUpdate()
        {
            if (m_CurrSceneIsLoading)
            {
                //模拟加载进度条
                m_TargetProgress = m_SceneHandle.Progress;
                if (m_CurrProgress < m_TargetProgress)
                {
                    //根据实际情况调节速度, 加载已完成和未完成, 模拟进度增值速度分开计算!
                    if (m_TargetProgress < 1)
                    {
                        m_CurrProgress += Time.deltaTime * 0.5f;
                    }
                    else
                    {
                        m_CurrProgress += Time.deltaTime * 0.8f;
                    }
                    m_CurrProgress = Mathf.Min(m_CurrProgress, m_TargetProgress);//这里是为了防止进度超过100%， 比如完成了显示102%
                    
                    //通过回调转发进度
                    LoadingUpdateAction?.Invoke(m_CurrProgress);

                    //通过监听事件转发进度
                    m_EventProgressValue.Value = m_CurrProgress;
                    GameEntry.Event.CommonEvent.Dispatch(EventType.UISceneLoadingProgressEvent, m_EventProgressValue);
                }

                if (m_CurrProgress == 1)
                {
                    GameEntry.Log(string.Format("场景加载完毕=={0}",m_CurrScreenName));
                    m_CurrSceneIsLoading = false;
                    m_OnComplete?.Invoke();
                }
            }
        }

        public void Dispose()
        {
            m_EventProgressValue = null;
        }
    }
}